""" dccadmin -- Admin via crappy DCC protocol"""
import asyncore, asynchat, socket
import re, struct

from pprint import PrettyPrinter

irc = None
pp = None

chat_sig = re.compile("\x01DCC CHAT CHAT (\d+) (\d+)\x01", re.I)

chats = []

class DCCChat(asynchat.async_chat):
    
    def __init__(self, ip, port):
        asynchat.async_chat.__init__(self)
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        host = struct.pack('L', socket.htonl(int(ip)))
        self.connect((socket.inet_ntoa(host), int(port)))

        self.buffer = []
        self.set_terminator('\n')

    def collect_incoming_data(self, data):
        self.buffer.append(data)

    def found_terminator(self):
        
        cmd = self.buffer[0]
        self.push(command_dispatcher(cmd))

        self.buffer = []


def init(bot):
    global irc, pp
    bot.cmd.events['PRIVMSG'].subscribe(privmsg)
    bot.cmd.events['QUIT'].subscribe(quit)
    irc = bot
    pp = PrettyPrinter(indent=4)

def privmsg(sender, args):
    global irc, pp, chat_sig, chats

    chat_req = chat_sig.match(args[0])
    if chat_req:
        ip = chat_req.group(1)
        port = chat_req.group(2)
        chats.append(DCCChat(ip, port))
        asyncore.loop()


def quit(sender, args):
    global chats
    for chat in chats:
        chat.push('Well, time to go!\n')
        chat.close()

def command_dispatcher(cmd):
    global irc

    mname, _, plist = cmd.partition(':')

    plist = plist.lstrip().replace('\;', '\x19').split(';')
    params = []
    for p in plist:
        params.append(p.lstrip().replace('\x19', ';'))

    if not hasattr(irc, mname):
        return "Sorry, I don't know '%s'\n" % mname

    method = getattr(irc, mname)

    try:
        method(*params)
    except TypeError:
        return method.__doc__ + "\n"
    except NameError:
        return "'%s' is not defined\n" % mname

    return "%s - ok\n" % mname
        
    
